package br.unicamp.ic.lis.docseaservice.filter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class LogFilter implements Filter {

	private static final String END_LINE = "\n";
	private static final String COLON = ": ";
	private static Logger LOG = Logger.getLogger(LogFilter.class);

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	private void doBeforeProcessing(ServletRequest request,
			ServletResponse response) throws IOException, ServletException {

		HttpServletRequest httpRequest = (HttpServletRequest) request;

		StringBuilder sb = new StringBuilder();
		sb.append("REQUEST").append(END_LINE);

		sb.append("INFO:\n");
		sb.append("Method: ").append(httpRequest.getMethod()).append(END_LINE);
		sb.append("URI: ").append(httpRequest.getRequestURI()).append(END_LINE);
		sb.append("Protocol: ").append(httpRequest.getProtocol())
				.append(END_LINE);
		sb.append("Content type: ").append(httpRequest.getContentType())
				.append(END_LINE);
		sb.append("Remote host: ").append(httpRequest.getRemoteHost())
				.append(END_LINE);
		sb.append("Remote address: ").append(httpRequest.getRemoteAddr())
				.append(END_LINE);

		sb.append("HEADER:\n");
		Enumeration<String> headerNames = httpRequest.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String headerName = headerNames.nextElement();
			sb.append(headerName).append(COLON)
					.append(httpRequest.getHeader(headerName)).append(END_LINE);
		}
		/*
		 * sb.append("BODY:\n");
		 * sb.append(getBody(httpRequest)).append(END_LINE);
		 */
		LOG.info(sb);
	}

	@SuppressWarnings("unused")
	private String getBody(HttpServletRequest httpRequest) {
		StringBuilder sb = new StringBuilder();
		BufferedReader bufferedReader = null;
		try {
			InputStream inputStream = httpRequest.getInputStream();
			if (inputStream != null) {
				bufferedReader = new BufferedReader(new InputStreamReader(
						inputStream));
				char[] charBuffer = new char[128];
				int bytesRead = -1;
				while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
					sb.append(charBuffer, 0, bytesRead);
				}
			} else {
				sb.append("");
			}
		} catch (IOException ex) {
			LOG.warn("Failed to read request body", ex);
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException ex) {
					LOG.error("Failed to close buffered reader", ex);
				}
			}
		}
		return sb.toString();
	}

	private void doAfterProcessing(ServletRequest request,
			ServletResponse response) throws IOException, ServletException {

		HttpServletResponse httpResponse = (HttpServletResponse) response;
		StringBuilder sb = new StringBuilder();
		sb.append("RESPONSE").append(END_LINE);
		sb.append("HTTP response code: ").append(httpResponse.getStatus())
				.append(END_LINE);
		sb.append("Content type: ").append(httpResponse.getContentType())
				.append(END_LINE);

		LOG.info(sb);
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		long beginTime = System.currentTimeMillis();
		doBeforeProcessing(request, response);
		chain.doFilter(request, response);
		doAfterProcessing(request, response);
		long endTime = System.currentTimeMillis();
		LOG.info("Total time: " + (endTime - beginTime) + "ms");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}
